#import <objc/runtime.h>
#import "UIView+Extension.h"

#define VIEWTHROUGH		@"passthrough"

@implementation UIView (Extension)
@dynamic passthrough;

+ (instancetype)viewWithColor:(UIColor *)color
{
	UIView *view = [[UIView alloc] init];
	view.backgroundColor = color;
	
	return view;
}

/*===================================================================
 说明:
    获取视图所在控制器
 ==================================================================*/
- (UIViewController *)viewController
{
    id vc = [self nextResponder];
    
    while (vc && ![vc isKindOfClass:[UIViewController class]])
    {
        vc = [vc nextResponder];
    }
    
    return vc;
}

+ (void)load
{
	Method fun = class_getInstanceMethod(self, @selector(willMoveToSuperview:));
	Method new = class_getInstanceMethod(self, @selector(fsWillMoveToSuperview:));
	method_exchangeImplementations(fun, new);
}

- (void)fsWillMoveToSuperview:(UIView *)newSuperview
{
	if (newSuperview == nil)
	{
		[[NSNotificationCenter defaultCenter] removeObserver:self name:APPLANGUAGE object:nil];
		objc_setAssociatedObject(self, APPLANGUAGE, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
		objc_setAssociatedObject(self, VIEWTHROUGH, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	}
	
	[self fsWillMoveToSuperview:newSuperview];
}

#pragma mark - 多语言支持
- (NSString *)language
{
	return objc_getAssociatedObject(self, APPLANGUAGE);
}

- (void)setLanguage:(NSString *)language
{
	objc_setAssociatedObject(self, APPLANGUAGE, language, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	
	if (language)
	{
		[self didLanguage];
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didLanguage) name:APPLANGUAGE object:nil];
	}
}

- (void)didLanguage
{
	//
}

#pragma mark - 穿透特性
- (void)setPassthrough:(BOOL)passthrough
{
	if (passthrough) self.backgroundColor = [UIColor clearColor];
	objc_setAssociatedObject(self, VIEWTHROUGH, @(passthrough), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)passthrough
{
	return [objc_getAssociatedObject(self, VIEWTHROUGH) boolValue];
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
	if (self.hidden || !self.userInteractionEnabled || self.alpha == 0) return NO;
	
	if (self.passthrough)		//穿透本视图，不穿透子视图
	{
		for (UIView *subView in self.subviews)
		{
			CGPoint subPoint = CGPointMake(point.x - subView.frame.origin.x, point.y - subView.frame.origin.y);
			if ([subView hitTest:subPoint withEvent:event]) return YES;
		}
		
		return NO;
	}
	
	return CGRectContainsPoint(self.bounds, point);
}

#pragma mark - 遍历视图
/*===================================================================
 说明:
	查找视图
 ==================================================================*/
- (BOOL)viewInView:(UIView *)view class:(Class)class handler:(ViewHandler)handler
{
	__block BOOL stop = NO;
	
	if ([view isKindOfClass:class]) handler(view, &stop);
	if (stop) return YES;
	
	for (NSInteger i=view.subviews.count; i; i--)
    {
		if ([self viewInView:view.subviews[i-1] class:class handler:handler]) return YES;
    }
	
	return NO;
}

- (BOOL)viewInView:(UIView *)view tag:(NSInteger)tag handler:(ViewHandler)handler
{
	__block BOOL stop = NO;
	
	if (view.tag == tag) handler(view, &stop);
	if (stop) return YES;
	
	for (NSInteger i=view.subviews.count; i; i--)
	{
		if ([self viewInView:view.subviews[i-1] tag:tag handler:handler]) return YES;
	}
	
	return NO;
}

- (void)viewWithClass:(Class)class handler:(ViewHandler)handler
{
	if (handler) [self viewInView:self class:class handler:handler];
}

- (void)viewWithTag:(NSInteger)tag handler:(ViewHandler)handler
{
	if (handler) [self viewInView:self tag:tag handler:handler];
}

#pragma mark - 特效
/*===================================================================
 说明:
    设置边框
 ==================================================================*/
- (void)setBorderWithWidth:(CGFloat)width radius:(CGFloat)radius color:(UIColor *)color
{
    self.layer.cornerRadius = radius;
    self.layer.borderWidth  = width;
    
    if (radius) self.layer.masksToBounds = YES;
    if (color) self.layer.borderColor = color.CGColor;
}

/*===================================================================
 说明:
    设置全圆形边框
 ==================================================================*/
- (void)setCircleWithWidth:(CGFloat)width color:(UIColor*)color
{
    CGFloat w = MIN(self.bounds.size.width, self.bounds.size.height);
    [self setBorderWithWidth:width radius:w / 2 color:color];
}

/*===================================================================
 说明:
    设置阴影
 ==================================================================*/
- (void)setShadowWithRadius:(CGFloat)radius color:(UIColor *)color
{
	[self setShadowWithRadius:radius color:color path:nil];
}

- (void)setShadowWithRadius:(CGFloat)radius color:(UIColor *)color path:(UIBezierPath *)path
{
    if (color) self.layer.shadowColor = color.CGColor;
    
    self.layer.shadowPath    = path ? path.CGPath : nil;
    self.layer.shadowOffset  = CGSizeZero;
	self.layer.shadowOpacity = (color && radius) ? 1 : 0;
    self.layer.shadowRadius  = radius;
}

/*===================================================================
 说明:
    设置模糊特效（IOS8以上）
 ==================================================================*/
- (UIView *)setBlurEffectWithStyle:(UIBlurEffectStyle)style withEdge:(UIRectEdge)edge
{
	//添加边线
	for (NSInteger i=1; i<=8; i<<=1)
	{
		if (edge & i)
		{
			UIView *line = [UIView viewWithColor:rgba(127, 127, 127, .3)];
			line.translatesAutoresizingMaskIntoConstraints = NO;
			[self insertSubview:line atIndex:0];
			
			NSLayoutConstraint *ch = [NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeHeight relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:.5];
			NSLayoutConstraint *cw = [NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeWidth relatedBy:0 toItem:nil attribute:0 multiplier:1 constant:.5];
			
			NSLayoutConstraint *cl = [NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeLeft relatedBy:0 toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
			NSLayoutConstraint *ct = [NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeTop relatedBy:0 toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:0];
			NSLayoutConstraint *cr = [NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeRight relatedBy:0 toItem:self attribute:NSLayoutAttributeRight multiplier:1 constant:0];
			NSLayoutConstraint *cb = [NSLayoutConstraint constraintWithItem:line attribute:NSLayoutAttributeBottom relatedBy:0 toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
			
			if (i == UIRectEdgeTop) [self addConstraints:@[ch, ct, cl, cr]];
			else if (i == UIRectEdgeLeft) [self addConstraints:@[cw, ct, cl, cb]];
			else if (i == UIRectEdgeBottom) [self addConstraints:@[ch, cb, cl, cr]];
			else if (i == UIRectEdgeRight) [self addConstraints:@[cw, ct, cr, cb]];
		}
	}
	
	//模糊特效视图(仅支持IOS8以上)
	if (IOS8)
    {
		self.backgroundColor = [UIColor clearColor];
        UIVisualEffectView *effect = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:style]];
        
        [self insertSubview:effect atIndex:0];
        [effect addConstraintEqualSuperview:self];
		
		return effect;
    }
	else
	{
		self.backgroundColor = style == UIBlurEffectStyleDark ? rgba(50, 50, 50, .94) : rgba(210, 210, 210, .94);
		return nil;
	}
}

- (UIView *)setSkinBlurEffect
{
	UIRectEdge edge = UIRectEdgeNone;
	
	for (NSLayoutConstraint *c in self.superview.constraints)
	{
		if ((c.firstItem == self && c.firstAttribute == NSLayoutAttributeBottom) || (c.secondItem == self && c.secondAttribute == NSLayoutAttributeBottom))
		{
			if (c.constant == 0) edge |= UIRectEdgeTop;
		}
	}
	
	return [self setSkinBlurEffectWithEdge:edge];
}

- (UIView *)setSkinBlurEffectWithEdge:(UIRectEdge)edge
{
	return [self setBlurEffectWithStyle:([MRSkinManager skin].nightMode ? UIBlurEffectStyleDark : UIBlurEffectStyleExtraLight) withEdge:edge];
}

#pragma mark - 视图约束
- (NSLayoutConstraint *)addConstraintWithWidth:(CGFloat)width
{
	NSLayoutConstraint *c = nil;
	if (width > 1.f)
	{
		c = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1 constant:width];
		[self addConstraint:c];
	}
	else
	{
		c = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeWidth multiplier:width constant:0];
		[self.superview addConstraint:c];
	}
	return c;
}

- (NSLayoutConstraint *)addConstraintWithHeight:(CGFloat)height
{
	NSLayoutConstraint *c = nil;
	if (height > 1.f)
	{
		c = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1 constant:height];
		[self addConstraint:c];
	}
	else
	{
		c = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeHeight multiplier:height constant:0];
		[self.superview addConstraint:c];
	}
	return c;
}

- (NSArray *)addConstraintEqualSuperview:(UIView *)superview
{
	return [self addConstraintEqualSuperview:superview withTop:0 withBottom:0];
}

- (NSArray *)addConstraintEqualSuperview:(UIView *)superview withTop:(CGFloat)top withBottom:(CGFloat)bottom
{
	self.translatesAutoresizingMaskIntoConstraints = NO;
	
	if (superview == self) return nil;
    if (superview != self.superview) [superview addSubview:self];
	
	NSArray *cs = @[[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeTop multiplier:1 constant:top],
					[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeBottom multiplier:1 constant:bottom],
					[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeLeft multiplier:1 constant:0],
					[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:superview attribute:NSLayoutAttributeRight multiplier:1 constant:0]];
	
	[superview addConstraints:cs];
	return cs;
}

- (NSArray *)getConstraintFromSuperview
{
	NSMutableArray *cs = [NSMutableArray array];
	
	for (NSLayoutConstraint *c in self.superview.constraints)
	{
		if (c.firstItem == self || c.secondItem == self) [cs addObject:c];
	}
	
	return cs;
}

- (void)removeConstraintFromSuperview
{
	if (self.translatesAutoresizingMaskIntoConstraints) return;
	
	[self.superview removeConstraints:[self getConstraintFromSuperview]];
}

- (void)disableConstraint
{
	if (self.translatesAutoresizingMaskIntoConstraints) return;
	
	[self removeConstraintFromSuperview];
	
	[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint * obj, NSUInteger idx, BOOL *stop) {
		
		if (obj.firstItem == self && (obj.secondItem == self || obj.secondItem == nil))
		{
			[self removeConstraint:obj];
		}
	}];
	
	self.translatesAutoresizingMaskIntoConstraints = YES;
}

#pragma mark - 视图绘图
/*===================================================================
 说明:
    渐变填充
 ==================================================================*/
+ (void)drawGradientWithRect:(CGRect)rect colors:(id)colors orientation:(UIInterfaceOrientation)orientation
{
	CGContextRef ctx = UIGraphicsGetCurrentContext();
	CGContextSaveGState(ctx);
	CGContextClipToRect(ctx, rect);
	
	if ([colors isKindOfClass:[UIColor class]])
	{
		[colors setFill];
		CGContextFillRect(ctx, rect);
	}
	else
	{
		CGPoint startPoint = UIInterfaceOrientationIsPortrait(orientation) ? CGPointMake(0, rect.origin.y) : CGPointMake(rect.origin.x, 0);
		CGPoint endPoint = UIInterfaceOrientationIsPortrait(orientation) ? CGPointMake(0, rect.origin.y + rect.size.height) : CGPointMake(rect.origin.x + rect.size.width, 0);
		
		if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationLandscapeLeft)
			[UIView drawLinearGradient:ctx colors:colors startPoint:startPoint endPoint:endPoint];
		else
			[UIView drawLinearGradient:ctx colors:colors startPoint:endPoint endPoint:startPoint];
	}
	
	CGContextRestoreGState(ctx);
}

+ (void)drawLinearGradient:(CGContextRef)ctx colors:(id)colors startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint
{
	NSArray *ary = colors;
	CGFloat clrs[ary.count][4];
	
    for (int i=0; i<ary.count; i++)
    {
        [colors[i] getRed:&clrs[i][0] green:&clrs[i][1] blue:&clrs[i][2] alpha:&clrs[i][3]];
    }
    
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, clrs[0], NULL, ary.count);
    CGColorSpaceRelease(rgb);
	
    CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
    CGGradientRelease(gradient);
}

+ (void)drawRadialGradient:(CGContextRef)ctx rect:(CGRect)rect colors:(id)colors start:(CGFloat)start end:(CGFloat)end
{
	NSArray *ary = colors;
	CGFloat clrs[ary.count][4];
	
	for (int i=0; i<ary.count; i++)
	{
		[colors[i] getRed:&clrs[i][0] green:&clrs[i][1] blue:&clrs[i][2] alpha:&clrs[i][3]];
	}
	
	CGFloat clip = rect.size.width / 2 - MIN(start, end);
	CGContextSaveGState(ctx);
	
	CGContextAddPath(ctx, [UIBezierPath bezierPathWithOvalInRect:rect].CGPath);
	CGContextAddPath(ctx, [UIBezierPath bezierPathWithOvalInRect:CGRectInset(rect, clip, clip)].CGPath);
	CGContextEOClip(ctx);
	
	CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
	CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, clrs[0], NULL, ary.count);
	CGColorSpaceRelease(rgb);
	
	CGPoint center = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
	
	CGContextDrawRadialGradient(ctx, gradient, center, start, center, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
	CGGradientRelease(gradient);
	
	CGContextRestoreGState(ctx);
}

@end
